package com.geekchique.runningbuddy.controller;

import java.util.ArrayList;
import java.util.List;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentReceiver;
import android.content.ServiceConnection;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;

import com.geekchique.runningbuddy.R;
import com.geekchique.runningbuddy.activity.CurrentRunMap;
import com.geekchique.runningbuddy.provider.ActivityID;
import com.geekchique.runningbuddy.service.IRemoteServiceCallback;
import com.geekchique.runningbuddy.service.IRemoteStopClockService;
import com.geekchique.runningbuddy.util.DBHelperImpl;
import com.geekchique.runningbuddy.util.IDBHelper;
import com.geekchique.runningbuddy.view.CurrentRunMapView;
import com.geekchique.runningbuddy.view.overlay.CurrentRunMapOverlay;
import com.geekchique.runningbuddy.view.overlay.DetailsOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayController;
import com.google.android.maps.Point;

public class CurrentRunMapControllerImpl implements ICurrentRunMapController{

	public CurrentRunMapView mapOfJogView;
	private MapController mapViewController;
	private CurrentRunMap mapOfJogActivity;
	private OverlayController overlayController;
	public Location currentGPSLocationOfPhone = null;
	protected LocationManager locationManager = null;
	protected IRemoteStopClockService messageService;
	private static final String TAG = CurrentRunMapControllerImpl.class.getName();
    protected LocationProvider provider;
	private String elapsedTime = "0";

	protected IDBHelper dbHelper;

    protected List<Location> path = new ArrayList<Location>();

	private CurrentRunMapOverlay googleMapOverlay;
	private DetailsOverlay detailsOverlay;

	public CurrentRunMapControllerImpl(CurrentRunMap mapOfJog) {
		this.mapOfJogActivity = mapOfJog;
		this.dbHelper = new DBHelperImpl();
	    this.locationManager =  (LocationManager)mapOfJog.getSystemService(Context.LOCATION_SERVICE);
	    Location location = locationManager.getCurrentLocation(ActivityID.GPS_PROVIDER);
	    this.setCurrentGPSLocationOfPhone(location);
	}

    /**
	 * IRemoteStopClockServiceInterface is defined through IDL
	 */
    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
		public void updatedStopwatch(String time) throws DeadObjectException {
			elapsedTime = time;
			currentRunMapHandler.sendMessage(currentRunMapHandler.obtainMessage(ActivityID.UPDATESTOPCLOCK));
		}
    };

    private ServiceConnection messageConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            messageService = IRemoteStopClockService.Stub.asInterface(service);
            try {
                messageService.registerStopClockUpdateListener(mCallback);
            } catch (DeadObjectException e) {
            	Log.v(TAG, "Tried to register with dead Object");
            }

        }

        public void onServiceDisconnected(ComponentName className) {
            messageService = null;
        }

    };

	protected Handler currentRunMapHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case ActivityID.UPDATESTOPCLOCK:
					detailsOverlay.setTime(elapsedTime);
					mapOfJogView.invalidateMapView();
					break;
				case ActivityID.STARTTRACKER:
					startTrackingRoute();
					break;
				case ActivityID.STOPTRACKER:
					stopTrackingRoute();
					break;
			}
			super.handleMessage(msg);
		}
	};
	private boolean serviceRunning;

	public void startTrackingRoute() {
		serviceRunning = true;
		final long MINIMUM_DISTANCECHANGE_FOR_UPDATE = 25; // in Meters
		final long MINIMUM_TIME_BETWEEN_UPDATE = 5000; // in Milliseconds
		List<LocationProvider> locProviders = locationManager.getProviders();
		provider = locProviders.get(0);
		provider = locationManager.getProvider(ActivityID.GPS_PROVIDER);

		mapOfJogActivity.startStopwatchService(messageConnection);
		this.locationManager.requestUpdates(provider, MINIMUM_TIME_BETWEEN_UPDATE,	MINIMUM_DISTANCECHANGE_FOR_UPDATE, new Intent(ActivityID.MY_LOCATION_CHANGED_ACTION));
	}

	public void stopTrackingRoute() {
		serviceRunning = false;
		mapOfJogActivity.stopStopwatchService(messageConnection);
		this.locationManager.removeUpdates(new Intent(ActivityID.MY_LOCATION_CHANGED_ACTION));
	}

	public void createMapOfJogView(MapView mapView) {
		this.mapOfJogView = new CurrentRunMapView(mapOfJogActivity, this, mapView);
		this.mapViewController = mapView.getController();

		this.overlayController = mapView.createOverlayController();

		this.googleMapOverlay =
			new CurrentRunMapOverlay(
					this.mapOfJogActivity,
					BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.map_start_point),
					BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.map_stop_point)
			);

		this.detailsOverlay = new DetailsOverlay(this.mapOfJogActivity, BitmapFactory.decodeResource(this.mapOfJogActivity.getResources(), R.drawable.dial));

		overlayController.add(googleMapOverlay, true);
		overlayController.add(detailsOverlay, false);

	}

	public void gotoCurrentGPSPosition() {

		Point point = new Point((int) (this.currentGPSLocationOfPhone.getLatitude() * 1000000), (int) (this.currentGPSLocationOfPhone.getLongitude() * 1000000));

		mapViewController.animateTo(point);
		mapViewController.zoomTo(18);
		mapOfJogView.invalidateMapView();

	}

//	private Point getMapPointFromLocationList(int pos) {
//		String[] loc = locations[pos][1].split(",");
//
//		double lat = Double.parseDouble(loc[1]);
//		double lon = Double.parseDouble(loc[0]);
//
//		return new Point((int) (lat * 1000000), (int) (lon * 1000000));
//	}

	public void zoomTo(int zoomLevel) {
		this.mapViewController.zoomTo(zoomLevel);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {

			switch (keyCode) {
				case KeyEvent.KEYCODE_I:
						mapViewController.zoomTo(mapOfJogView.getZoomLevel() + 1);
						break;
				case KeyEvent.KEYCODE_O:
						mapViewController.zoomTo(mapOfJogView.getZoomLevel() - 1);
						break;
				case KeyEvent.KEYCODE_V:
					stopTrackingRoute();
					break;
				case KeyEvent.KEYCODE_B:
					startTrackingRoute();
					break;
				case KeyEvent.KEYCODE_N:
					draw3Point();
					break;
				case KeyEvent.KEYCODE_M:
					draw4Point();
					break;
				case KeyEvent.KEYCODE_L:
					drawPoints();
					break;
				case KeyEvent.KEYCODE_S:
					mapOfJogView.toggleSatellite();
					break;
				case KeyEvent.KEYCODE_BACK:
					stopPlottingJog();
					mapOfJogActivity.finish();
		      }

		      return true;
	}

	private void stopPlottingJog() {

	}

	public void draw1Point() {
		addPoint(55846809, -4229920);
	}

	public void draw2Point() {
		addPoint(55846809, -4231200);
	}

	public void draw3Point() {
		addPoint(55851200, -4236400);
	}

	public void draw4Point() {
		addPoint(55851000, -4236800);
	}


    private boolean addPoint(double latitude, double longitude) {
    	Location pointLocation = new Location();
    	pointLocation.setLatitude(latitude);
    	pointLocation.setLongitude(longitude);
    	this.googleMapOverlay.addLocationToPath(pointLocation);
		mapOfJogView.invalidateMapView();
    	return true;
    }

	public void drawPoints() {
		draw1Point();
		draw2Point();
		draw3Point();
		draw4Point();
	}

	public void updateRunningPath() {
		if(this.currentGPSLocationOfPhone != null){
			Log.v(TAG,"Updating a jogging a current jogging route.");
			Location location = locationManager.getCurrentLocation(ActivityID.GPS_PROVIDER);
			Log.i(TAG, "Updating longitude: "+location.getLongitude() + ", latitude: "+location.getLatitude());
			this.setCurrentGPSLocationOfPhone(location);

			Location pointLocation = new Location();
	    	pointLocation.setLatitude(this.currentGPSLocationOfPhone.getLatitude() * 1000000);
	    	pointLocation.setLongitude(this.currentGPSLocationOfPhone.getLongitude() * 1000000);
	    	this.googleMapOverlay.addLocationToPath(pointLocation);
			gotoCurrentGPSPosition();
		}
	}

	public void setCurrentGPSLocationOfPhone(Location currentLocation) {
		this.currentGPSLocationOfPhone = currentLocation;
	}

	public boolean getIfServiceIsRunning() {
		return serviceRunning;
	}

	public void setServiceRunning(boolean serviceisrunning) {
		this.serviceRunning = serviceisrunning;
	}



}
